import type { AxiosRequestConfig, Method } from '@types/axios'
import axios from 'axios'
// import router from '/@/router/index'



interface LoadingInstance {
    target: any
    count: number
}
interface Options {
    // 是否开启取消重复请求, 默认为 true
    CancelDuplicateRequest?: boolean
    // 是否开启loading层效果, 默认为false
    loading?: boolean
    // 是否开启简洁的数据结构响应, 默认为true
    reduceDataFormat?: boolean
    // 是否开启接口错误信息展示,默认为true
    showErrorMessage?: boolean
    // 是否开启code不为0时的信息提示, 默认为true
    showCodeMessage?: boolean
    // 是否开启code为0时的信息提示, 默认为false
    showSuccessMessage?: boolean
    // 当前请求使用另外的用户token
    anotherToken?: string
}

window.requests = []
window.tokenRefreshing = false
const pendingMap = new Map()
const loadingInstance: LoadingInstance = {
    target: null,
    count: 0,
}



/**
 * 处理异常
 * @param {*} error
 */
function httpErrorStatusHandle(error: any) {
    // 处理被取消的请求
    if (axios.isCancel(error)) return console.error('取消重复请求')
    let message = ''
    if (error && error.response) {
        switch (error.response.status) {
            case 302:
                message = '接口重定向'
                break
            case 400:
                message = '参数不正确'
                break

            default:
                message = '异常'
                break
        }
    }

    if (error.message.includes('Network')){
        // message = window.navigator.onLine ? console.log('服务器异常') : console.log('您已断开连接！')
    }

    /**
     * 关闭Loading层实例
     */
    function closeLoading(options: Options) {
        if (options.loading && loadingInstance.count > 0) loadingInstance.count--
        if (loadingInstance.count === 0) {
            loadingInstance.target.close()
            loadingInstance.target = null
        }
    }

    /**
     * 储存每个请求的唯一cancel回调, 以此为标识
     */
    function addPending(config: AxiosRequestConfig) {
        const pendingKey = getPendingKey(config)
        config.cancelToken = config.cancelToken ||  new axios.CancelToken((cancel) => {
                if (!pendingMap.has(pendingKey)) {
                    pendingMap.set(pendingKey, cancel)
                }
            })
    }

    /**
     * 删除重复的请求
     */
    function removePending(config: AxiosRequestConfig) {
        const pendingKey = getPendingKey(config)
        if (pendingMap.has(pendingKey)) {
            const cancelToken = pendingMap.get(pendingKey)
            cancelToken(pendingKey)
            pendingMap.delete(pendingKey)
        }
    }

    /**
     * 生成每个请求的唯一key
     */
    function getPendingKey(config: AxiosRequestConfig) {
        let { data } = config
        const { url, method, params, headers } = config
        if (typeof data === 'string') data = JSON.parse(data) // response里面返回的config.data是个字符串对象
        return [
            url,
            method,
            headers && (headers as anyObj).batoken ? (headers as anyObj).batoken : '',
            headers && (headers as anyObj)['ba-user-token'] ? (headers as anyObj)['ba-user-token'] : '',
            JSON.stringify(params),
            JSON.stringify(data),
        ].join('&')
    }

    /**
     * 根据请求方法组装请求数据/参数
     */
    // export function requestPayload(method: Method, data: anyObj) {
    //     if (method == 'GET') {
    //         return {
    //             params: data,
    //         }
    //     } else if (method == 'POST') {
    //         return {
    //             data: data,
    //         }
    //     }
    // }


/**
 * 根据运行环境获取基础请求URL
 */
 const getUrl = (): string => {
    const value: string = import.meta.env.VITE_AXIOS_BASE_URL as string
    // console.log(value, value == 'getCurrentDomain' ? window.location.protocol + '//' + window.location.host : value)
    // return value == 'getCurrentDomain' ? window.location.protocol + '//' + window.location.host : value
    return value ? value : window.location.protocol + '//' + window.location.host
}


/**
 * 创建`Axios`
 * 默认开启`reductDataFormat(简洁响应)`,返回类型为`ApiPromise`
 * 关闭`reductDataFormat`,返回类型则为`AxiosPromise`
 */
function createAxios<Data = any, T = ApiPromise<Data>>(axiosConfig: AxiosRequestConfig, options: Options = {}, loading = {}): T {
    const Axios = axios.create({
        baseURL:  getUrl(),//base,
        timeout: 1000 * 10,
        responseType: 'json',
    })

    options = Object.assign(
        {
            CancelDuplicateRequest: true, // 是否开启取消重复请求, 默认为 true
            loading: false, // 是否开启loading层效果, 默认为false
            reduceDataFormat: true, // 是否开启简洁的数据结构响应, 默认为true
            showErrorMessage: true, // 是否开启接口错误信息展示,默认为true
            showCodeMessage: true, // 是否开启code不为1时的信息提示, 默认为true
            showSuccessMessage: false, // 是否开启code为1时的信息提示, 默认为false
            anotherToken: '', // 当前请求使用另外的用户token
        },
        options
    )

    // 请求拦截
    Axios.interceptors.request.use(
        (config) => {
            removePending(config)
            options.CancelDuplicateRequest && addPending(config)
            // 创建loading实例
            if (options.loading) {
                loadingInstance.count++
                if (loadingInstance.count === 1) {
                    // loadingInstance.target = ElLoading.service(loading)
                }
            }

            // 自动携带token
            if (config.headers) {
                const token = '获取token'
                if (token) (config.headers as anyObj).batoken = '设置token'
                const userToken = options.anotherToken || '设置token'
                if (userToken) (config.headers as anyObj)['ba-user-token'] = userToken
            }

            return config
        },
        (error) => {
            return Promise.reject(error)
        }
    )

    // 响应拦截
    Axios.interceptors.response.use(
        (response) => {
            removePending(response.config)
            options.loading && closeLoading(options) // 关闭loading StatusCode

            if ((response.data && response.data.code == 1) || response.data.StatusCode == 200) {
                return options.reduceDataFormat ? response.data : response
            }

            if (response.config.responseType == 'json') {
                if (response.data && response.data.code !== 1) {

                    if (options.showCodeMessage) {
                        console.error(response.data.msg)
                    }
                    // 自动跳转到路由name或path
                    if (response.data.code == 302) {
                        // router.push({ path: response.data.data.routePath ?? '', name: response.data.data.routeName ?? '' })
                    }
                    if (response.data.code == 303) {

                        // router.push({ path: '/login' })
                    }
                    // code不等于1, 页面then内的具体逻辑就不执行了
                    return Promise.reject(response.data)
                } else if (options.showSuccessMessage && response.data && response.data.code == 1) {

                }
            }
        },
        (error) => {
            error.config && removePending(error.config)
            options.loading && closeLoading(options) // 关闭loading
            options.showErrorMessage && httpErrorStatusHandle(error) // 处理错误状态码
            return Promise.reject(error) // 错误继续返回给到具体页面
        }
    )
    return Axios(axiosConfig) as T
}



export default createAxios



/*
 * 感谢掘金@橙某人提供的思路和分享
 * 本axios封装详细解释请参考：https://juejin.cn/post/6968630178163458084?share_token=7831c9e0-bea0-469e-8028-b587e13681a8#heading-27
 */
